package com.biz.primus.ms.sms.service.provider;

import com.biz.primus.model.misc.enums.ApiExceptionType;
import com.biz.primus.model.misc.enums.NotAvailableExceptionType;
import com.biz.primus.model.misc.exception.ProviderNotAvailableException;
import com.biz.primus.model.misc.utils.HttpUtils;
import com.biz.primus.model.misc.utils.XmlUtils;
import com.biz.primus.model.misc.vo.HuaxinResponseVo;
import com.biz.primus.model.misc.vo.MultiReceiverShortMessageVo;
import com.biz.primus.model.misc.vo.ProviderResponse;
import com.biz.primus.model.misc.vo.ShortMessageVo;
import com.biz.primus.ms.sms.sdk.huaxin.MD5;
import com.biz.primus.ms.sms.service.model.ServiceProvider;
import com.google.common.base.Joiner;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpException;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * @author yanweijin
 * @date 2017/5/30
 */
@Service
@Slf4j
public class HuaxinSMS implements ServiceProvider {

    @Value("${provider.huaxin.username}")
    private String accountName;
    @Value("${provider.huaxin.password}")
    private String password;
    @Value("${provider.huaxin.debug-mode}")
    private boolean debugMode;

    private String TEST_URL = "http://118.26.163.246/sms.aspx";
    private String TEST_ACCOUNT_NAME = "cs0003";
    private String TEST_PASSWORD = "cs0003";

    private String URL = "https://dx.ipyy.net/sms.aspx";
    private static Random debugRandom = new Random();

    @PostConstruct
    void init() {
        log.debug("provider-huaxin debug mode = {}", debugMode);
        password = MD5.GetMD5Code(password).toUpperCase();
        TEST_PASSWORD = MD5.GetMD5Code(TEST_PASSWORD).toUpperCase();
    }
    @Override
    public String getProviderId() {
        return "huaxin";
    }
    @Override
    public String getProviderName() {
        return "华信";
    }
    @Override
    public boolean isDefaultProvider() {
        return false;
    }

    private long nextMs() {
        return (debugRandom.nextInt(300) + 50);
    }
    @Override
    public ProviderResponse send(ShortMessageVo sm) throws ProviderNotAvailableException {
        try {
            HttpPost postRequest = createPostRequest(Action.send, sm.getMobile(), sm.getFullText());
            if (debugMode) {
                Thread.sleep(nextMs());
                ProviderResponse providerResponse = new ProviderResponse("压力测试短信");
                providerResponse.setOriginalMessage("压力测试短信");
                return providerResponse;
            }
            String returnString = HttpUtils.executePostRequest(postRequest);
            HuaxinResponseVo internalResp = XmlUtils.xml2obj(returnString, HuaxinResponseVo.class);
            return handleResponse(internalResp);

        } catch (ProviderNotAvailableException e) {
            throw e;
        } catch (Exception e) {
            log.warn("send msg occur ex", e);
            return new ProviderResponse(ApiExceptionType.SYSTEM_ERROR, e.getMessage());
        }
    }

    private ProviderResponse handleResponse(HuaxinResponseVo internalResp) throws ProviderNotAvailableException {
        switch (internalResp.getReturnStatus()) {
            case "Success":
            case "OK":
                return new ProviderResponse(internalResp.getTaskId());
            case "AmountNotEnough":
                throw new ProviderNotAvailableException(NotAvailableExceptionType.NSF);
            default:
                throw new ProviderNotAvailableException(NotAvailableExceptionType.OTHER,
                        internalResp.getReturnStatus() + "," + internalResp.getMessage());

        }
    }

    @Override
    public ProviderResponse massSend(ShortMessageVo... sm) {
        throw new UnsupportedOperationException();
    }
    @Override
    public ProviderResponse massSend(MultiReceiverShortMessageVo multiReciverShortMessage) throws ProviderNotAvailableException {

        String receivers = Joiner.on(",").join(multiReciverShortMessage.getMobiles()).trim();
        String content = multiReciverShortMessage.getFullText();
        try {
            HttpPost postRequest = createPostRequest(Action.send, receivers, content);
            String returnString = HttpUtils.executePostRequest(postRequest);
            HuaxinResponseVo internalResp = XmlUtils.xml2obj(returnString, HuaxinResponseVo.class);
            return handleResponse(internalResp);
        } catch (ProviderNotAvailableException e) {
            throw e;
        } catch (Exception e) {
            log.warn("send msg occur ex", e);
            return new ProviderResponse(ApiExceptionType.SYSTEM_ERROR, e.getMessage());
        }
    }
    @Override
    public long getBalance() throws ProviderNotAvailableException {

        HttpPost postRequest = createPostRequest(Action.overage, "", "");
        String returnString = null;
        try {
            returnString = HttpUtils.executePostRequest(postRequest);
        } catch (HttpException e) {
            throw new ProviderNotAvailableException(NotAvailableExceptionType.OTHER, e.getMessage());
        }
        HuaxinResponseVo internalResponse = XmlUtils.xml2obj(returnString, HuaxinResponseVo.class);
        ProviderResponse resp = handleResponse(internalResponse);
        if (resp.isSuccess()) {
            return internalResponse.getOverage();
        }
        throw new ProviderNotAvailableException(NotAvailableExceptionType.OTHER, resp.getOriginalMessage());

    }

    @Override
    public void pullDeliveryStateAndPersist() {

    }


    private HttpPost createPostRequest(Action action, String receivers, String content) {
        HttpPost post = new HttpPost(getUrl());
        post.setHeader("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        nvps.add(new BasicNameValuePair("action", action.toString()));
        nvps.add(new BasicNameValuePair("userid", ""));
        nvps.add(new BasicNameValuePair("account", getAccountName()));
        nvps.add(new BasicNameValuePair("password", getPassword()));
        //多个手机号用逗号分隔
        nvps.add(new BasicNameValuePair("sendTime", ""));
        nvps.add(new BasicNameValuePair("mobile", receivers));
        nvps.add(new BasicNameValuePair("content", content));
        nvps.add(new BasicNameValuePair("extno", ""));
        log.debug("request body = {}", nvps);
        try {
            post.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));
        } catch (UnsupportedEncodingException e) {
            //ignore
            throw new RuntimeException(e);
        }
        return post;
    }


    private enum Action {
        send, overage
    }

    private String getAccountName() {
        if (debugMode) {
            return TEST_ACCOUNT_NAME;
        }
        return accountName;
    }

    private String getPassword() {
        if (debugMode) {
            return TEST_PASSWORD;
        }
        return password;
    }

    private String getUrl() {
        if (debugMode) {
            return TEST_URL;
        }
        return URL;
    }
}
